package com.ucode.application.controller.sys;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.validation.constraints.Size;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.ucode.application.form.sys.RoleForm;
import com.ucode.sys.model.Role;
import com.ucode.sys.service.RoleService;
import com.ucode.sys.service.UserService;
import com.ucode.sys.vo.RoleVo;
import com.ucode.sys.vo.UserVo;
import com.ucode.tool.base.MapVo;
import com.ucode.tool.base.Paginator;
import com.ucode.tool.base.ResponseResult;
import com.ucode.tool.base.ResultCodeEnum;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;

@Api(tags="角色管理")
@RestController
@RequestMapping("/sys-role")
@Validated
public class RoleController {

    @Autowired
    private RoleService roleService;
    @Autowired
    private UserService userService;
    
    @PreAuthorize("hasAuthority('sys:role:read') or hasRole('ADMIN')")
    @ApiOperation("根据条件分页查询列表")
    @GetMapping(value = "/list")
    public ResponseResult<Object> findPage(
            @ApiParam(value ="所属子系统")  @RequestParam(value = "subSys",required = false) Integer subSys,
            @ApiParam(value ="角色名称")  @RequestParam(value = "name",required=false) String name,
            @ApiParam(value="页码",example="1") @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
            @ApiParam(value="每页记录数",example="20") @RequestParam(value = "pageSize", defaultValue = "20") Integer pageSize){
        
        if(StrUtil.isNotBlank(name))
            name = StrUtil.concat(true, name,"%");
        
        Paginator<Role> paginator = roleService.queryPage(subSys,name, pageNum, pageSize);
        
        return ResponseResult.success(paginator);
    }
    
    @PreAuthorize("hasAuthority('sys:role:read') or hasRole('ADMIN')")
    @ApiOperation("根据条件分页查询角色授权用户列表")
    @ApiImplicitParam(name = "roleId", value = "角色ID", required = true, dataType = "String",paramType = "path")
    @GetMapping(value = "/users/{roleId}")
    public ResponseResult<Object> findRoleUserPage(@PathVariable(name="roleId",required=true) Long roleId,
            @ApiParam(value ="用户姓名")  @RequestParam(value = "realname",required=false) String realname,
            @ApiParam(value="页码",example="1") @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
            @ApiParam(value="每页记录数",example="20") @RequestParam(value = "pageSize", defaultValue = "20") Integer pageSize){
        
        if(StrUtil.isNotBlank(realname))
            realname = StrUtil.concat(true, realname,"%");
        
        Paginator<UserVo> paginator = userService.queryPageRoleUsers(roleId, realname, pageNum, pageSize);
        List<UserVo> users = paginator.getList();
        if(CollUtil.isNotEmpty(users)){
            List<Long> userIds =users.stream().map(m -> m.getId()).distinct().collect(Collectors.toList());
            
            List<MapVo<Long, String>> mapvo = roleService.findUserRoleNames(userIds);
            if(CollUtil.isNotEmpty(mapvo)){
                Map<Long, String> userRoleNameMap = mapvo.stream().collect(Collectors.toMap(MapVo::getKey,MapVo::getValue,(key1, key2) -> key1));
                if(MapUtil.isNotEmpty(userRoleNameMap)){
                    List<UserVo> list = new ArrayList<UserVo>();
                    for(UserVo userVo : users){
                        userVo.setRoleNames(userRoleNameMap.get(userVo.getId()));
                        list.add(userVo);
                    }
                    paginator.setList(list);
                }
            }
        }
        return ResponseResult.success(paginator);
    }
    
    @PreAuthorize("hasAuthority('sys:role:read') or hasRole('ADMIN')")
    @ApiOperation(value="根据主键查询")
    @ApiImplicitParam(name = "id", value = "主键ID", required = true, dataType = "String",paramType = "path")
    @GetMapping("/getById/{id}")
    public ResponseResult<Object> getById(@PathVariable(name="id",required=true) Long id){
        
        Role role = roleService.findById(id);
        if(role == null){
            return ResponseResult.result(ResultCodeEnum.NO_RECORD);
        }
        
        List<Long> menuIds = roleService.findMenuIdsByRoleId(role.getId());
        RoleVo roleVo = new RoleVo(role,menuIds);
        return ResponseResult.success(roleVo);
    }
    
    @PreAuthorize("hasAuthority('sys:role:write') or hasRole('ADMIN')")
    @ApiOperation(value="创建")
    @PostMapping("/create")
    public ResponseResult<Object> create(@Validated @RequestBody RoleForm form) {
        
        Role role = new Role();
        role.setName(form.getName());
        role.setSubSys(form.getSubSys());
        role.setDataType(form.getDataType());
        role.setRemark(form.getRemark());
        role = roleService.insert(role);
        if(role != null && CollUtil.isNotEmpty(form.getMenuIds())){
            roleService.updateRoleMenus(role.getId(), form.getMenuIds());
        }
        
        return role != null ? ResponseResult.success(role) : ResponseResult.failed();
    }
    
    @PreAuthorize("hasAuthority('sys:role:write') or hasRole('ADMIN')")
    @ApiOperation(value="更新")
    @ApiImplicitParam(name = "id", value = "角色ID", required = true, dataType = "String",paramType = "path")
    @PostMapping("/update/{id}")
    public ResponseResult<Object> update(@PathVariable(name="id",required=true) Long id,
            @Validated @RequestBody RoleForm form) {
        
        Role role = new Role();
        role.setName(form.getName());
        role.setSubSys(form.getSubSys());
        role.setDataType(form.getDataType());
        role.setRemark(form.getRemark());
        role.setId(id);
        int i = roleService.update(role);
        
        if(i > 0 && form.getMenuIds() != null){
            //更新时,如果MenuIds为空则代表不更新，如果是空数组或者非空数组则表示更新
            roleService.updateRoleMenus(id, form.getMenuIds());
        }
        
        return i > 0 ? ResponseResult.success() : ResponseResult.failed();
    }
    
    @PreAuthorize("hasAuthority('sys:role:write') or hasRole('ADMIN')")
    @ApiOperation(value="复制")
    @ApiImplicitParam(name = "id", value = "角色ID", required = true, dataType = "String",paramType = "path")
    @PostMapping("/copy/{id}")
    public ResponseResult<Object> copy(@PathVariable(name="id",required=true) Long id) {
        Role role = roleService.findById(id);
        if(role == null){
            return ResponseResult.result(ResultCodeEnum.NO_RECORD);
        }
        List<Long> menuIds = roleService.findMenuIdsByRoleId(role.getId());
        
        role = roleService.insert(role);
        if(role != null && CollUtil.isNotEmpty(menuIds)){
            roleService.updateRoleMenus(role.getId(), menuIds);
        }
        return role != null ? ResponseResult.success(role) : ResponseResult.failed();
    }
    
    @PreAuthorize("hasAuthority('sys:menu:write') or hasRole('ADMIN')")
    @ApiOperation(value="删除")
    @ApiImplicitParam(name = "id", value = "角色ID", required = true, dataType = "String",paramType = "path")
    @PostMapping("/delete/{id}")
    public ResponseResult<Object> delete(@PathVariable(name="id",required=true) Long id) {
        roleService.deleteById(id);
        return ResponseResult.success();
    }
    
    @PreAuthorize("hasAuthority('sys:menu:write') or hasRole('ADMIN')")
    @ApiOperation(value="批量删除")
    @PostMapping("/delete")
    public ResponseResult<Object> delete(
            @ApiParam(value ="角色ID(最多100条)")  @Size(min=1,max = 100,message="一次最多选择100条")@RequestParam(value = "ids") List<Long> ids) {
        roleService.delete(ids);
        return ResponseResult.success();
    }
    
    @PreAuthorize("hasAuthority('sys:role:write') or hasRole('ADMIN')")
    @ApiOperation(value="角色关联用户")
    @ApiImplicitParam(name = "roleId", value = "角色ID", required = true, dataType = "String",paramType = "path")
    @PostMapping("/relatedUsers/{roleId}")
    public ResponseResult<Object> relatedUsers(@PathVariable(name="roleId",required=true) Long roleId,
            @ApiParam(value ="用户(最多100条)") @Size(min=1,max = 100,message="一次最多选择100条") @RequestParam(value = "userIds",required = true) List<Long> userIds){
        roleService.relatedRoleUsers(roleId, userIds);
        return ResponseResult.success();
    }
    
    @PreAuthorize("hasAuthority('sys:role:write') or hasRole('ADMIN')")
    @ApiOperation(value="取消角色关联用户")
    @ApiImplicitParam(name = "roleId", value = "角色ID", required = true, dataType = "String",paramType = "path")
    @PostMapping("/unRelatedUsers/{roleId}")
    public ResponseResult<Object> unRelatedUsers(@PathVariable(name="roleId",required=true) Long roleId,
            @ApiParam(value ="用户(最多100条)") @Size(min=1,max = 100,message="一次最多选择100条") @RequestParam(value = "userIds",required = true) List<Long> userIds){
        roleService.unRelatedRoleUsers(roleId, userIds);
        return ResponseResult.success();
    }
}
